<template>
  <div ref="antvFlow" :class="['antv-flow', {'antv-flow-full': fullscreen}]" :style="'height:' + contentHeight + 'px'">
    <!-- <el-dialog :title="title" :visible.sync="antvVisible" @opened="opened" @closed="closed" size="full"> -->
    <div class="container-warp">
      <div class="operating" v-if="!readonly">
        <div class="btn-group">
          <div :class="['antv-btn', {'btn-disabled': haveStart || disabled}]" title="开始节点" @mousedown="startDrag('Start', $event)">
            <i class="iconfont icon-flow-round-rectangle"></i>
          </div>
          <div :class="['antv-btn', {'btn-disabled': haveEnd || disabled}]" title="结束节点" @mousedown="startDrag('End', $event)">
            <i class="iconfont icon-flow-round-rectangle"></i>
          </div>
          <div :class="['antv-btn', {'btn-disabled': disabled}]" title="循环节点" @mousedown="startDrag('Circle', $event)">
            <i class="iconfont icon-flow-round"></i>
          </div>
          <div :class="['antv-btn', {'btn-disabled': disabled}]" title="任务节点" @mousedown="startDrag('Rect', $event)">
            <i class="iconfont icon-flow-rectangle"></i>
          </div>
          <div :class="['antv-btn', {'btn-disabled': disabled}]" title="条件节点">
            <i class="iconfont icon-flow-rhombus" @mousedown="startDrag('polygon', $event)"></i>
          </div>
          <div class="btn-group-tips" v-if="showTips">
            拖拽生成</br>拓扑图形
          </div>
        </div>
        <div class="btn-group">
          <el-tooltip :open-delay="openDelay" effect="dark" content="直线箭头" placement="bottom">
            <div :class=" ['antv-btn', currentArrow === 1 && !disabled ? 'currentArrow' : '', {'btn-disabled': disabled}]" @click="changeEdgeType('normal')">
              <i class="iconfont icon-flow-bottomarrow"></i>
            </div>
          </el-tooltip>
          <el-tooltip :open-delay="openDelay" content="曲线箭头" placement="bottom">
            <div :class=" ['antv-btn', currentArrow === 2 && !disabled ? 'currentArrow' : '', {'btn-disabled': disabled}]" @click="changeEdgeType('smooth')">
              <i class="iconfont icon-flow-curvearrow"></i>
            </div>
          </el-tooltip>
          <el-tooltip :open-delay="openDelay" content="直角箭头" placement="bottom">
            <div :class=" ['antv-btn', currentArrow === 3 && !disabled ? 'currentArrow' : '', {'btn-disabled': disabled}]" @click="changeEdgeType()">
              <i class="iconfont icon-flow-brokenline"></i>
            </div>
          </el-tooltip>
        </div>
        <div class="btn-group">
          <el-tooltip :open-delay="openDelay" content="撤销" placement="bottom">
            <div :class="['antv-btn', {'btn-disabled': !canUndo || disabled}]" @click="onUndo">
              <i class="iconfont icon-flow-back"></i>
            </div>
          </el-tooltip>
          <el-tooltip :open-delay="openDelay" content="重做" placement="bottom">
            <div :class="['antv-btn', {'btn-disabled': !canRedo || disabled}]" @click="onRedo">
              <i class="iconfont icon-flow-forward"></i>
            </div>
          </el-tooltip>
        </div>
        <!-- <div class="btn-group">
          <div class="antv-btn" @click="changeMode('edit')" title="选择模式">
            <i class="iconfont icon-mousepointershubiao"></i>
          </div>
          <div class="antv-btn" @click="changeMode('drag')" title="拖拽模式">
            <i class="iconfont icon-tuozhuai"></i>
          </div>
        </div> -->
        <div class="btn-group">
          <el-tooltip :open-delay="openDelay" :content="fullscreen ? '取消全屏' : '全屏'" placement="bottom">
            <div class="antv-btn" @click="toggleFullscreen">
              <i class="iconfont icon-fullscreen" v-show="!fullscreen"></i>
              <i class="iconfont icon-cancel-fullscreen" v-show="fullscreen"></i>
            </div>
          </el-tooltip>
        </div>
        <div class="btn-group">
          <el-tooltip :open-delay="openDelay" content="删除" placement="bottom">
            <div :class="['antv-btn', {'btn-disabled': selectCellNum == 0 || disabled}]" @click="deleteNode()" style="margin-top: 5px;">
              <i class="iconfont icon-flow-delete"></i>
            </div>
          </el-tooltip>
          <!-- <el-tooltip :open-delay="openDelay" content="保存流程图并生成java代码" placement="bottom">
            <div class="antv-btn" @click="saveFlow">
              <i class="iconfont icon-flow-save"></i>
            </div>
          </el-tooltip> -->
          <el-tooltip :open-delay="openDelay" content="生成图片" placement="bottom">
            <div class="antv-btn" @click="savePic">
              <i class="iconfont icon-flow-download-pic"></i>
            </div>
          </el-tooltip>
        </div>
        <div class="btn-group">
          <el-popover class="opt-tip" placement="right" title="操作提示" width="200" trigger="click">
            <ul>
              <li class="opt-tip-item">1、拖动节点生成流程图型</li>
              <li class="opt-tip-item">2、Ctrl + 滚轮：缩放</li>
              <li class="opt-tip-item">3、Shift + 鼠标移动：画布移动</li>
            </ul>
            <el-button type="text" slot="reference"><i class="el-icon-information"></i></el-button>
          </el-popover>
        </div>
      </div>
      <div ref="graphContainer"></div>
      <RightDrawer v-if="!readonly" v-show="isOpening" ref="rightDrawer" :disabled="disabled" class="right-drawer" :checkEntity="checkEntity" :contentHeight="contentHeight" :curEntityList="curEntityList" :drawerType="type" :selectCellNum="selectCellNum" :selectCell="selectCell" :graph="graph" :grid="grid" @deleteNode="deleteNode"></RightDrawer>
    </div>
    <!-- </el-dialog> -->
  </div>
</template>
<script>
// Addon
import { Graph, Shape, FunctionExt, DataUri } from '@antv/x6';
import RightDrawer from './src/right-drawer';
import insertCss from 'insert-css';
import { startDragToGraph } from './src/methods.js';
import './font-icon/iconfont.css';
import { saveFlow } from '@/api/ruleConfig/flow';
import CONSTANT from '@/api/constant';
// import { has } from '@antv/x6/lib/util/object/object';
// import { defaults } from '@antv/x6/lib/registry/router/manhattan/options';
const data = {};
export default {
  props: {
    visible: Boolean,
    title: {
      type: String,
      default: '流程图'
    },
    entityList: Array,
    checkEntity: Array,
    dataForm: Object,
    taskinfo2: Object,
    disabled: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    width: Number,
    height: Number
  },
  data() {
    return {
      diabledEntity: false,  //  关联模型禁用
      openDelay: 1500,
      isOpening: false,
      fullscreen: false,  // 全屏显示
      selectCellNum: 0,
      contentWidth: 0,
      contentHeight: 0,
      graph: null,
      value1: true,
      type: 'grid',
      selectCell: '',
      connectEdgeType: {  //连线方式
        connector: 'normal',
        router: {
          name: ''
        }
      },
      showTips: false,
      currentArrow: 1,
      grid: { // 网格设置
        showGrid: true,
        size: 20,      // 网格大小 10px
        visible: true, // 渲染网格背景
        type: 'mesh',
        args: {
          color: '#D0D0D0',
          thickness: 1,     // 网格线宽度/网格点大小
          factor: 10,
        },
      },
      canUndo: false,
      canRedo: false,
      haveStart: false,  //已有开始或结束
      haveEnd: false,
      // curEntityList: [],
      /****************节点数据存储******************/
      // dataList: [], // 所有节点
      // nodeList: [], // 所有node节点
      // circleList: [], // 所有循环节点
      // pointList: [], // 所有连接线
      // judgeNodeList: [], // 所有判断节点
      // njudgeNodeList: [], // 所有否判断节点
      // circlePointList: [], // 所有循环连接线
      /*******************************************/
    }
  },
  components: {
    RightDrawer
  },
  computed: {
    antvVisible: {
      get() {
        return this.visible;
      },
      set(val) {
        this.$emit('update:visible', val);
      }
    },
    //当前实体类
    curEntityList() {
      let curEntityList = [];
      let arr = JSON.parse(JSON.stringify(this.checkEntity));
      arr.forEach(item => {
        this.entityList.forEach(e => {
          let id = e.entityId + '';
          if (item === id) {
            curEntityList.push(e);
          }
        });
      });
      return curEntityList;
    }
  },
  methods: {
    // 计算main主体高度
    getMainHeight(e) {
      /* this.contentHeight = Math.max(window.innerHeight - 60, 400);
      this.contentWidth = window.innerWidth - 250;
      if (e) {
        //画布调整大小
        this.graph.resize(this.contentWidth, this.contentHeight);
      } */
      this.contentWidth = this.$refs['graphContainer'].parentNode.offsetWidth;
      this.contentHeight = 910;
    },
    //初始化流程图数据
    initFlowData() {
      /* //当前实体类
      this.curEntityList = [];
      let arr = JSON.parse(JSON.stringify(this.checkEntity));
      arr.forEach(item => {
        this.entityList.forEach(e => {
          let id = e.entityId + '';
          if (item === id) {
            this.curEntityList.push(e);
          }
        });
      }); */
      //初始化右侧数据
      this.$refs.rightDrawer.init();
    },
    //初始化画布
    initX6() {
      let _that = this;
      // window.addEventListener('resize', this.debounceHeight);
      this.graph = new Graph({
        container: this.$refs['graphContainer'],
        width: this.width || this.contentWidth,
        height: this.height || this.contentHeight,
        grid: this.grid,
        panning: {
          enabled: true,
          modifiers: 'shift'
        }, //平移
        resizing: { //调整节点宽高
          enabled: true,
          orthogonal: false,
        },
        selecting: true, //可选
        snapline: true,
        interacting: {
          edgeLabelMovable: true
        },
        connecting: { // 节点连接
          anchor: 'center',
          connectionPoint: 'anchor',
          allowBlank: false,
          snap: true,
          createEdge() {
            return new Shape.Edge({
              attrs: {
                line: {
                  stroke: '#1890ff',
                  strokeWidth: 1,
                  targetMarker: {
                    name: 'classic',
                    size: 8
                  },
                  strokeDasharray: 0, //虚线
                  style: {
                    animation: 'ant-line 30s infinite linear',
                  },
                },
              },
              label: {
                text: ''
              },
              connector: _that.connectEdgeType.connector,
              router: {
                name: _that.connectEdgeType.router.name || ''
              },
              zIndex: 0
            })
          },
        },
        highlighting: {
          magnetAvailable: {
            name: 'stroke',
            args: {
              padding: 4,
              attrs: {
                strokeWidth: 4,
                stroke: '#6a6c8a'
              }
            }
          }
        },
        //滚动
        scroller: {
          enabled: false
        },
        //小地图
        minimap: {
          enabled: !this.readonly,
          container: !this.readonly ? this.$refs['rightDrawer'].$refs['miniMap'] : '',
          width: 300,
          height: 150,
          padding: 5
        },
        //缩放
        mousewheel: {
          enabled: true,
          modifiers: ['ctrl', 'meta'],
        },
        // 历史
        history: {
          enabled: true,
        },
        //框选
        selecting: {
          enabled: true,
          rubberband: true
        },
      });
      insertCss(`
              @keyframes ant-line {
                to {
                    stroke-dashoffset: -1000
                }
              }
            `)
      this.graph.fromJSON(data);
      this.graph.history.redo();
      this.graph.history.undo();
      // 鼠标移入移出节点
      this.graph.on('node:mouseenter', FunctionExt.debounce(() => {
        const container = this.$refs['graphContainer']
        const ports = container.querySelectorAll('.x6-port-body')
        this.showPorts(ports, true)
      }), 500);
      this.graph.on('node:mouseleave', () => {
        const container = this.$refs['graphContainer']
        const ports = container.querySelectorAll('.x6-port-body')
        this.showPorts(ports, false)
      });
      this.graph.on('blank:click', () => {
        this.type = 'grid';
        //选中网格需清空选中节点的数据
        this.selectCell = '';
      });
      this.graph.on('cell:click', ({ cell }) => {
        this.type = cell.isNode() ? 'node' : 'edge';
        this.$emit('cellClick', cell);
      });
      //监听框选
      this.graph.on('selection:changed', args => {
        //记录当前选中的数量
        this.selectCellNum = args.selected.length;
        if (this.selectCellNum > 1) {
          //只有选中一个节点时才允许修改节点信息
          this.type = 'grid';
          this.selectCell = '';
        } else {
          this.selectCell = args.added[0];
        }
        args.added.forEach(cell => {
          // this.selectCell = cell
          if (cell.isEdge()) {
            cell.isEdge() && cell.attr('line/strokeDasharray', 5) //虚线蚂蚁线
            cell.addTools([
              {
                name: 'vertices',
                args: {
                  padding: 4,
                  attrs: {
                    strokeWidth: 0.1,
                    stroke: '#2d8cf0',
                    fill: '#ffffff',
                  }
                },
              },
            ])
          }
        })
        args.removed.forEach(cell => {
          cell.isEdge() && cell.attr('line/strokeDasharray', 0);  //正常线
          cell.removeTools();
        })
      });
      /**
       * 处理history
       */
      //监听撤销
      this.graph.history.on('undo', args => {
        // code here
        this.$emit('historyUndo', args);
      });
      //监听重做
      this.graph.history.on('redo', args => {
        // code here
        this.$emit('historyRedo', args);
      });
      this.graph.history.on('change', () => {
        this.historyChange();
      });
      // 监听节点新增
      this.graph.on('node:added', args => {
        const { cell } = args;
        // 检查禁用情况
        this.checkNode();
        //选中
        this.graph.resetSelection(cell);
        this.type = 'node';
        const data = cell.store.data;
        switch (data.attrs.nodeData.type) {
          case 'Start':
            //开始
            this.haveStart = true;
            break;
          case 'End':
            //结束
            this.haveEnd = true;
            break;
        }
      });
      //监听节点删除
      this.graph.on('node:removed', args => {
        const { cell } = args;
        const data = cell.store.data;
        // 检查禁用情况
        this.checkNode();
        switch (data.attrs.nodeData.type) {
          case 'Start':
            //开始
            this.haveStart = false;
            break;
          case 'End':
            //结束
            this.haveEnd = false;
            break;
        }
      });
      //边连接
      this.graph.on('edge:connected', args => {
        //选中节点
        this.graph.resetSelection(args.edge);
        this.type = 'edge';
        // console.log(args.edge)
      })
    },
    showPorts(ports, show) {
      for (let i = 0, len = ports.length; i < len; i = i + 1) {
        ports[i].style.visibility = show ? 'visible' : 'hidden'
      }
    },
    // 拖拽生成正方形或者圆形
    startDrag(type, e) {
      if (this.disabled) {
        return;
      }
      //只能有一个开始和结束
      if (type === 'Start') {
        if (this.haveStart) {
          return;
        }
      } else if (type === 'End') {
        if (this.haveEnd) {
          return;
        }
      }
      startDragToGraph(this.graph, type, e);
    },
    // 删除节点
    deleteNode() {
      if (this.disabled) {
        return;
      }
      const cell = this.graph.getSelectedCells();
      this.graph.removeCells(cell);
      this.type = 'grid';
    },
    // 保存png
    savePic() {
      this.$nextTick(() => {
        this.graph.toPNG(dataUri => {
          // 下载
          DataUri.downloadDataUri(dataUri, this.title + '.png');
        }, {
          backgroundColor: 'white',
          padding: {
            top: 50,
            right: 50,
            bottom: 50,
            left: 50
          },
          quality: 1,
          copyStyles: false
        })
      })
    },
    //流程图完整性校验
    checkFlow() {
      const graphToJson = this.graph.toJSON();
      const { cells } = graphToJson;
      /**
       * 1、完整的流程图必需包含开始节点和结束节点且仅有一个
       * 2、每个节点必定有至少一条与其他节点的连接线；
       * 3、开始节点只能是连接线起点
       * 4、结束节点只能是连接线终点
       */
      let errs = [], //错误消息集合
        nodeList = [],
        edgeList = [],
        startNum = 0,
        endNum = 0,
        len = cells.length,
        alls = [],   //所有节点
        edges = [];  //与其他节点有连接关系的节点集合（不包含自己与自己连接的）
      if (len === 0) {
        errs.push('画布不能为空');
      } else {
        for (let i = 0; i < len; i++) {
          //非连线(节点)
          if (cells[i].shape !== 'edge') {
            //节点数据
            const nodeData = cells[i].attrs.nodeData;
            //节点名称
            const nodeText = cells[i].attrs.label.text;
            const flowNode = nodeData.flowNode;
            if (nodeData.type === 'Start') {
              startNum++;
            } else if (nodeData.type === 'End') {
              endNum++;
            } else if (nodeData.type === 'Rect') {
              let errTxt = '任务节点【' + nodeText + '】';
              switch (flowNode.flowNodeType) {
                case '':
                  errs.push(errTxt + '未选择节点类型');
                  break;
                case '2':
                  //执行规则组
                  if (flowNode.groupIdentify === '') {
                    errs.push(errTxt + '未选择执行规则组');
                  }
                  break;
                case '6':
                  //子流程
                  if (flowNode.childFlowIdentify === '') {
                    errs.push(errTxt + '未选择子流程');
                  }
                  break;
                case '7':
                  //源码节点
                  if (flowNode.methodName === '') {
                    errs.push(errTxt + '未选择方法');
                  } else if (flowNode.hasMethodParams && flowNode.methodParams === '') {
                    errs.push(errTxt + '方法未输入参数');
                  }
                  break;
              }
            } else if (nodeData.type === 'polygon') {
              const errTxt = '条件节点【' + nodeText + '】';
              //处理条件节点的边
              let conditionEdges = this.graph.getOutgoingEdges(cells[i].id);
              if (conditionEdges) {
                conditionEdges = conditionEdges.filter(item => {
                  return item.source.cell !== item.target.cell;
                });
                let trueNum = 0,
                  falseNum = 0;
                conditionEdges.forEach(item => {
                  let labelText = item.store.data.labels[0].attrs.label.text;
                  if (labelText === '是') {
                    trueNum++;
                  } else if (labelText === '否') {
                    falseNum++;
                  }
                });
                if (trueNum < 1) {
                  errs.push(errTxt + '缺少是判断的连线');
                } else if (trueNum > 1) {
                  errs.push(errTxt + '过多是判断的连线');
                }
                if (falseNum < 1) {
                  errs.push(errTxt + '缺少否判断的连线');
                } else if (falseNum > 1) {
                  errs.push(errTxt + '过多否判断的连线');
                }
              }
              //校验条件表单
              if (flowNode.flowJudges.length < 1) {
                errs.push(errTxt + '未选择判断条件');
              }
            }
            alls.push({
              id: cells[i].id,
              type: cells[i].attrs.nodeData.type
            });
            nodeList.push(cells[i]);
          } else {
            //连接线
            if (cells[i].source.cell !== cells[i].target.cell) {
              edges.push({
                source: cells[i].source.cell,
                target: cells[i].target.cell
              });
            }
            edgeList.push(cells[i]);
          }
        }

        if (startNum !== 1) {
          errs.push('开始节点必需存在，且仅有一个');
        }
        if (endNum !== 1) {
          errs.push('结束节点必需存在，且仅有一个');
        }

        let startEdgeErr = false,
          endEdgeErr = false,
          edgeErr = false;
        //遍历所有节点
        alls.forEach(item => {
          let hasEdge = false;
          for (let i = 0, len = edges.length; i < len; i++) {
            if (item.id === edges[i].source || item.id === edges[i].target) {
              hasEdge = true;
            }
            if (item.type === 'Start') {
              if (item.id === edges[i].target && !startEdgeErr) {
                startEdgeErr = true;
                errs.push('开始节点不能为连线终点');
              }
            } else if (item.type === 'End') {
              if (item.id === edges[i].source && !endEdgeErr) {
                endEdgeErr = true;
                errs.push('结束节点不能为连线起点');
              }
            }
          }
          if (!hasEdge && !edgeErr) {
            edgeErr = true;
            errs.push('节点间必需有连接线关联');
          }
        });
      }
      return {
        graphToJson,
        nodeList,
        edgeList,
        errs
      };
    },
    //根据节点类型获取节点flowShapeStatus
    getFlowShapeStatus(flowNodeType) {
      const flowTypes = CONSTANT.ruleConfig.flowTypes;
      const obj = flowTypes.find(item => {
        return item.value === flowNodeType;
      });
      return obj ? obj.status : '';
    },
    /**
     * 数据组装
     * @param {Array} nodes 节点
     * @param {Array} edges 边
     */
    packageData(nodes, edges) {
      let oldStartId = '', //旧结束id
        oldEndId = '',  //新结束id
        newStartId = 'begin',
        newEndId = 'end',    
        idMap = {}, // 新旧id映射，给每一个节点都添加
        index = 1; // 累加
      const nodeList = nodes.map(item => {
        /**********保存id映射*********/ 
        idMap[item.id] = 'node' + index;
        index ++;
        /****************************/
        const { label, nodeData } = item.attrs;
        const flow = nodeData.flowNode;
        let flowNodeType = '',
          flowShapeId = item.id,
          flowNode = 'node',
          flowNextNode = '',
          flowShapeStatus = '',
          entityId = '', //循环实体
          itemId = '',   //实体属性
          groupIdentify = '',   //执行规则组
          childFlowIdentify = '',  //子流程
          methodName = '',   //方法名称
          methodParams = '',  //方法参数
          methodExp = '',  //
          methodType = '',
          flowJudges = null; //条件
        switch (nodeData.type) {
          case 'Start':
            //开始
            this.haveStart = true;
            flowNodeType = '1';
            flowNode = 'root';
            oldStartId = flowShapeId;
            flowShapeId = newStartId;
            break;
          case 'End':
            //结束
            this.haveEnd = true;
            flowNodeType = '1';
            flowNode = 'root';
            oldEndId = flowShapeId;
            flowShapeId = newEndId;
            break;
          case 'Rect':
            //任务节点
            flowNodeType = flow.flowNodeType;
            flowShapeId = idMap[flowShapeId]; // 使用映射的id
            switch (flowNodeType) {
              case '2': //执行规则组
                groupIdentify = flow.groupIdentify;
                break;
              case '6':  //子流程
                childFlowIdentify = flow.childFlowIdentify;
                break;
              case '7':  //源码节点
                methodName = flow.methodName;
                methodParams = flow.methodParams;
                methodExp = flow.methodExp;
                methodType = flow.methodType;
                break;
            }
            break;
          case 'Circle':
            //循环节点
            flowNodeType = '3';
            flowShapeId = idMap[flowShapeId]; // 使用映射的id
            entityId = flow.entityId;
            itemId = flow.itemId;
            break;
          case 'polygon':
            //条件节点
            flowNodeType = '5';
            flowShapeId = idMap[flowShapeId]; // 使用映射的id
            flowJudges = flow.flowJudges
            break;
        }
        flowShapeStatus = this.getFlowShapeStatus(flowNodeType);

        //获取下一步节点id
        for (let i = 0, len = edges.length; i < len; i++) {
          if (edges[i].source.cell === item.id) {
            flowNextNode = edges[i].target.cell;
            break;
          }
        }
        return {
          flowShapeName: label.text,
          flowNode: flowNode,
          flowShapeId: flowShapeId,
          flowShapeX: item.position.x,
          flowShapeY: item.position.y,
          flowShapeStatus: flowShapeStatus, // status
          flowNextNode: flowNextNode, //
          flowNodeType: flowNodeType, // 1-root节点,2-执行规则节点,3-循环节点,4-其他
          seq: item.zIndex,
          // 节点参数
          curEntitys: JSON.stringify(this.checkEntity),
          entityId: entityId, //循环实体
          itemId: itemId,   //实体属性
          groupIdentify: groupIdentify,   //执行规则组
          childFlowIdentify: childFlowIdentify,  //子流程
          methodName: methodName,   //方法名称
          methodParams: methodParams,  //方法参数  
          methodExp: methodExp,
          methodType: methodType,
          flowJudges: flowJudges //条件
        }
      })
      // 连线
      const pointList = edges.map((item, index) => {
        return {
          source: item.source.cell === oldStartId ? newStartId : item.source.cell === oldEndId ? newEndId : idMap[item.source.cell], //替换连线开始为开始节点的id
          edgeId: 'edge' + (index + 1),//item.id,
          pointType: 'next',
          target: item.target.cell === oldEndId ? newEndId : item.target.cell === oldStartId ? newStartId : idMap[item.target.cell],  //替换连接结束为结束节点的id
          seq: item.zIndex,
        }
      })
      // 节点
      const dataList = nodeList.map(item => {
        item.flowNextNode = item.flowNextNode === oldEndId ? newEndId : item.flowNextNode === oldStartId ? newStartId : idMap[item.flowNextNode];
        return item;
      })
      return {
        dataList,
        pointList
      }
    },

    //保存流程图
    saveFlow() {
      // 先取消所有选中的节点和边, 防止把选中状态一起保存了
      this.graph.cleanSelection();
      const { errs, nodeList, edgeList, graphToJson } = this.checkFlow();
      if (errs.length > 0) {
        const h = this.$createElement;
        const liEles = [];
        errs.forEach((item, idx) => {
          liEles.push(h('li', { style: 'line-height: 20px;' }, [
            h('span', null, idx + 1 + '、' + item)
          ]));
        })
        this.$msgbox({
          title: '流程图异常提示',
          type: 'warning',
          message: h('div', null, [
            h('ul', null, liEles)
          ]),
          showCancelButton: false,
          confirmButtonText: '确定',
        }).then(_ => { }).catch(_ => { });
      } else {
        //这里处理保存数据的操作，可迁移到edit-flow组件
        const { dataList, pointList } = this.packageData(nodeList, edgeList);
        this.saveInfo(dataList, pointList, graphToJson);
      }
    },
    /**
     * 提交保存
     * @param {Array} dataList 封装后的节点数据
     * @param {Array} pointList 封装后的连线数据
     * @param {Object} graphToJson 完整的 graph.toJSON()对象
     */
    saveInfo(dataList, pointList, graphToJson) {
      // 判断条件
      let flowJudes = [];
      dataList.forEach((item) => {
        if (item.flowNodeType === '5' && item.flowJudges) {
          item.flowJudges.forEach((i) => {
            i.flowId = item.flowId;
            i.flowShapeId = item.flowShapeId;
            flowJudes.push(i);
          });
        }
      });
      // 流程图完整的数据
      this.dataForm.flowImg = JSON.stringify({
        graph: graphToJson,
        grid: this.grid
      });
      let params = {
        dataForm: JSON.stringify(this.dataForm),
        relList: JSON.stringify(this.checkEntity),
        flows: JSON.stringify(dataList),
        points: JSON.stringify(pointList),
        judges: JSON.stringify(flowJudes),
        taskNo: this.taskinfo2.taskNo
        // flowImg: JSON.stringify(graphToJson)
      };
      this.$store.dispatch('loading/CHANGE_LOADING', true);
      saveFlow(params)
        .then(res => {
          this.$store.dispatch('loading/CHANGE_LOADING', false);
          if (res.data && res.data.resultCode === 0) {
            this.$message.success(res.data.resultMsg);
            // this.$parent.toList();
            this.$emit('save-success');
          } else {
            this.$message.error(res.data.resultMsg);
          }
        })
        .catch(err => {
          this.$store.dispatch('loading/CHANGE_LOADING', false);
        });
    },
    // 改变边形状
    changeEdgeType(e) {
      if (this.disabled) {
        return;
      }
      if (e === 'normal') {
        this.connectEdgeType = {
          connector: 'normal',
          router: { name: '' }
        }
        this.currentArrow = 1;
      } else if (e === 'smooth') {
        this.connectEdgeType = {
          connector: 'smooth',
          router: { name: '' }
        }
        this.currentArrow = 2;
      } else {
        this.connectEdgeType = {
          connector: 'normal',
          router: { name: 'manhattan' }
        }
        this.currentArrow = 3;
      }
    },
    //历史状态改变
    historyChange() {
      this.canUndo = this.graph.history.canUndo();
      this.canRedo = this.graph.history.canRedo();
    },
    //撤销
    onUndo() {
      if (this.disabled) {
        return;
      }
      this.graph.history.undo();
    },
    //重做
    onRedo() {
      if (this.disabled) {
        return;
      }
      this.graph.history.redo();
    },
    //销毁画布
    destroy() {
      if (this.graph) {
        this.graph.dispose();
      }
    },
    // opened() {
    init() {
      this.isOpening = true;
      this.type = 'grid';
      this.selectCell = '';
      this.getMainHeight();
      this.initX6();
      if (this.readonly) {
        return;
      }
      this.initFlowData();
      if (this.disabled) {
        return;
      }
      setTimeout(() => {
        this.showTips = true;
      }, 1000);
      setTimeout(() => {
        this.showTips = false;
      }, 5000);
    },
    // 根据数据渲染流程图
    applyFlowData(data) {
      if (data) {
        data = JSON.parse(data);
        if (data.graph){
          this.graph.fromJSON(data.graph);
          this.grid = data.grid;  
        } else {
          this.graph.fromJSON(data);
        }        
        // 检查关联模型是否可以修改
        this.checkNode(true);
        // 回显的数据默认都有开始和结束节点
        this.haveStart = true;
        this.haveEnd = true;
        // 居中画布
        this.centerFlow();
      }
    },
    // 居中画布
    centerFlow() {
      this.graph.centerContent();
    },
    // 清空画布
    clearFlow() {
      this.graph.clearCells();
    },
    /**
     * 检查是否可以禁用关联模型
     * 当节点中存在非开始和结束节点时不允许编辑 
     */ 
    checkNode(checkStartAndEnd) {
      const node = this.graph.getNodes();
      const ignores = ['Start', 'End'];
      let diabledEntity = false;
      for (let i = node.length - 1; i > -1; i--) {
        if (ignores.indexOf(node[i].attrs.nodeData.type) < 0) {
          diabledEntity = true;
          if (!checkStartAndEnd) {
            break;
          }
        } else if (checkStartAndEnd) {
          if (node[i].attrs.nodeData.type === 'Start') {
            this.haveStart = true;
          } else {
            this.haveEnd = true;
          }
        }
      }
      this.diabledEntity = diabledEntity;
    },
    // 全屏或取消全屏
    toggleFullscreen() {
      this.fullscreen = !this.fullscreen;
      if (this.fullscreen) {
        document.body.classList.add('overflow-hidden');
        this.$nextTick(() => {
          let antvFlow = this.$refs.antvFlow;
          this.graph.resize(antvFlow.offsetWidth, antvFlow.offsetHeight);
        });        
      } else {
        document.body.classList.remove('overflow-hidden');
        this.graph.resize(this.width || this.contentWidth, this.height || this.contentHeight);
      }  
    }
    /* closed() {
      this.isOpening = false;
      window.removeEventListener('resize', this.debounceHeight);
      this.destroy();
    } */
  },
  /*mounted() {
    this.init();
  }
   beforeCreate() {
    this.debounceHeight = FunctionExt.debounce(e => { this.getMainHeight(e) }, 100);
  },
  destroyed() {
    window.removeEventListener('resize', this.debounceHeight);
  }, */
};
</script>
<style lang="less" scoped>
// @import './font-icon/iconfont.css';
@import "./style/index.less";
.x6-widget-dnd {
  z-index: 10000;
}
</style>